/**
 * 客户端唯一ID生成器
 * 基于硬件信息生成唯一的客户端标识
 */
const os = require('os');
const crypto = require('crypto');
const { getInstance: getDatabase } = require('./database');
const logger = require('./logger');

class ClientIdManager {
  constructor() {
    this.clientId = null;
  }

  /**
   * 生成基于硬件的唯一客户端ID（纯硬件ID，不含时间戳）
   * 相同硬件永远生成相同的ID
   */
  generateHardwareId() {
    try {
      // 收集硬件信息（只使用稳定的硬件特征）
      const macAddresses = this.getMacAddresses();
      
      const hardwareInfo = {
        // MAC地址（最稳定的硬件标识）
        mac: macAddresses.sort().join(','), // 排序确保一致性
        // CPU型号（不包含速度，因为可能变化）
        cpuModel: os.cpus()[0]?.model || 'UNKNOWN',
        // 平台
        platform: os.platform(),
        // 架构
        arch: os.arch(),
        // 操作系统类型
        type: os.type(),
        // 主机名（可选，可能会变化）
        // hostname: os.hostname()
      };

      // 创建硬件指纹
      const fingerprint = JSON.stringify(hardwareInfo);
      const hash = crypto.createHash('sha256').update(fingerprint).digest('hex');
      
      // 生成客户端ID：格式 client_<hardware_hash>（纯硬件ID）
      const clientId = `client_${hash}`;
      
      logger.info('✅ 生成硬件ID:', clientId);
      logger.info('📋 硬件指纹:', {
        platform: hardwareInfo.platform,
        arch: hardwareInfo.arch,
        cpuModel: hardwareInfo.cpuModel,
        macAddresses: macAddresses,
        hardwareHash: hash.substring(0, 16)
      });

      return clientId;
    } catch (error) {
      logger.error('❌ 生成硬件ID失败:', error);
      // 如果硬件信息获取失败，生成一个随机但稳定的ID
      // 使用主机名作为后备方案
      const fallbackId = crypto.createHash('sha256')
        .update(`${os.hostname()}_${os.platform()}_${os.arch()}`)
        .digest('hex');
      return `client_fallback_${fallbackId}`;
    }
  }

  /**
   * 获取MAC地址列表（用于硬件ID生成）
   * 只获取物理网卡的MAC地址，排除虚拟网卡
   */
  getMacAddresses() {
    try {
      const interfaces = os.networkInterfaces();
      const macAddresses = new Set(); // 使用Set去重

      for (const name in interfaces) {
        // 排除虚拟网卡和临时接口
        const isVirtual = name.toLowerCase().includes('virtual') || 
                         name.toLowerCase().includes('vmware') ||
                         name.toLowerCase().includes('vbox') ||
                         name.toLowerCase().includes('docker');
        
        if (isVirtual) continue;

        for (const iface of interfaces[name]) {
          // 只要非内部接口且有有效MAC地址
          if (!iface.internal && iface.mac && iface.mac !== '00:00:00:00:00:00') {
            macAddresses.add(iface.mac.toLowerCase()); // 统一为小写
          }
        }
      }

      const result = Array.from(macAddresses);
      return result.length > 0 ? result : ['NO_MAC'];
    } catch (error) {
      logger.error('获取MAC地址失败:', error);
      return ['NO_MAC'];
    }
  }

  /**
   * 从数据库加载客户端ID
   */
  async loadFromDatabase() {
    try {
      const db = await getDatabase();
      const result = await db.get('SELECT value FROM app_config WHERE key = ?', ['client_id']);
      
      if (result && result.value) {
        logger.info('从数据库加载客户端ID:', result.value);
        return result.value;
      }

      return null;
    } catch (error) {
      logger.error('从数据库加载客户端ID失败:', error);
      return null;
    }
  }

  /**
   * 保存客户端ID到数据库
   */
  async saveToDatabase(clientId) {
    try {
      const db = await getDatabase();
      await db.run(
        'INSERT OR REPLACE INTO app_config (key, value) VALUES (?, ?)',
        ['client_id', clientId]
      );
      logger.info('客户端ID已保存到数据库');
    } catch (error) {
      logger.error('保存客户端ID到数据库失败:', error);
      throw error;
    }
  }

  /**
   * 初始化客户端ID（优先使用缓存）
   * 
   * 工作流程：
   * 1. 首先从数据库缓存加载（永久缓存）
   * 2. 如果缓存不存在，基于硬件信息生成新ID
   * 3. 将生成的ID保存到数据库永久缓存
   * 4. 相同硬件重新安装后会生成相同的ID
   */
  async initialize() {
    try {
      logger.info('🔧 初始化客户端ID...');

      // 📦 步骤1：尝试从数据库缓存加载
      this.clientId = await this.loadFromDatabase();

      if (this.clientId) {
        logger.info('✅ 从缓存加载客户端ID:', this.clientId);
      } else {
        // 🆕 步骤2：缓存不存在，基于硬件生成新ID
        logger.info('💡 缓存中无客户端ID，基于硬件信息生成...');
        this.clientId = this.generateHardwareId();
        
        // 💾 步骤3：保存到数据库永久缓存
        await this.saveToDatabase(this.clientId);
        logger.info('💾 客户端ID已保存到缓存');
      }

      logger.info('✅ 客户端ID初始化完成:', this.clientId);
      logger.info('🔑 ID类型: 纯硬件ID（相同硬件=相同ID）');
      return this.clientId;
    } catch (error) {
      logger.error('❌ 初始化客户端ID失败:', error);
      // 如果失败，直接生成硬件ID（不依赖数据库）
      this.clientId = this.generateHardwareId();
      logger.warn('⚠️  使用未缓存的硬件ID:', this.clientId);
      return this.clientId;
    }
  }

  /**
   * 获取客户端ID
   */
  getClientId() {
    if (!this.clientId) {
      logger.warn('客户端ID未初始化！');
      return null;
    }
    return this.clientId;
  }

  /**
   * 重新生成客户端ID（慎用）
   */
  async regenerate() {
    logger.warn('重新生成客户端ID...');
    this.clientId = this.generateHardwareId();
    await this.saveToDatabase(this.clientId);
    return this.clientId;
  }
}

// 导出单例
module.exports = new ClientIdManager();
